/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import sheduler.Manager;

/**
 *
 * @author Peewhy
 */
public class Server {
    public static final String CRLF = "\r\n";
    public static final String VERSION = "HTTP/1.0";
    public static final int SERVER_PORT = 80;
    public static final String LOG = "server";
    public static final String LOG_filename = "log.txt";
    public static final int MAX_THREADS = 10;
    
    private ContentType contentType;
    public ServerConfig config;
    public static final String DEFAULT_CONFIG = "default.cfg";
    public Logger logger;
    private ExecutorService pool;
    boolean shutDown;

    
    ServerSocket httpSocket;
    Socket connectionSocket;
    Router router;
    Manager manager;
    
    
    public ServerConfig getConfig(){
        return config;
    }
    
    public Router getRouter() {
    	return router;
    }
    
    public Manager getManager() {
    	return manager;
    }
    
    
    public String getContentType(String extension) {
        return contentType.getContentType(extension);
    }
     
 
    
    public Server() throws Exception {
        contentType = new ContentType();
        router = new Router();
        manager = new Manager();        
    	router.addServlet("/send", new SenderServlet(this));
    	router.addServlet("/status", new StatusServlet(this));
    	router.addServlet("/stop", new StopServlet(this));
        loadServer();        
    }
    
    public void shutDown() throws IOException {
        logger.log(Level.INFO, "Server is shutting down");
        pool.shutdown();
        shutDown = true;
        httpSocket.close();
        connectionSocket.close();
    }
    
    public void start() {    	
        try {
        	httpSocket = new ServerSocket(config.getPort());            
            while (!shutDown) {
                logger.log(Level.INFO, "Request from client");
                connectionSocket = httpSocket.accept();
                pool.execute(new HttpThread(this, connectionSocket));
            }
        }
        catch (IOException ie) {
            logger.log(config.getLevel(), "Internal webserver error", ie.getMessage());
        }   
        catch (Exception e) {
        	logger.log(config.getLevel(), "Internal webserver error", e.getMessage());
        }
    }

    // Initiliazes logging and assings handlers for it.
    private void initLogging() throws SecurityException, IOException {
        logger = Logger.getLogger(LOG);
        logger.setLevel(Level.ALL);                
        
        Handler fh = new FileHandler(LOG_filename);
        logger.addHandler(fh);

        Handler ch = new ConsoleHandler();
        logger.addHandler(ch);


        SimpleFormatter sf = new SimpleFormatter();
        fh.setFormatter(sf);
    }

    private void loadDefaultConfig() {
        config = new ServerConfig();
        try {
            config.loadFromFile(DEFAULT_CONFIG);
        } catch (IOException er) {
            logger.log(Level.WARNING, "Error while reading server config file, using defaults");
        }
    }

    public void loadServer() throws IOException, SecurityException {
        shutDown = false;
        initLogging();
        logger.log(Level.ALL, "Web server is starting on " + new Date());
        loadDefaultConfig();
        pool = Executors.newFixedThreadPool(MAX_THREADS);
    }
}
